Pendulum

%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation, PillowWriter  

Import system module

from pydae import ssa
from pendulum import pendulum_class
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-3-440574a2138a> in <module>
----> 1 from pydae import ssa
      2 from pendulum import pendulum_class

~\anaconda3\envs\workenv\lib\site-packages\pydae\ssa.py in <module>
      8 
      9 import numpy as np
---> 10 import pandas as pd
     11 import scipy
     12 

ModuleNotFoundError: No module named 'pandas'
p = pendulum_class()
M = 30.0
L = 5.21
p.initialize([{'f_x':0,'M':M,'L':L,'theta':np.deg2rad(0)}],-1)
p.report_x()
p.report_u()
pos_x = -0.00
pos_y = -5.21
v_x   = -0.00
v_y   = -0.00
f_x   = -0.00
ssa.eval_A(p)
eig_df=ssa.damp_report(p)
eig_df
Real Imag Freq. Damp
Mode 1 -1.666667e-08 1.372194 0.218391 1.214600e-08
Mode 2 -1.666667e-08 -1.372194 0.218391 1.214600e-08
Mode 3 -1.666667e-08 1902.424498 302.780263 8.760751e-12
Mode 4 -1.666667e-08 -1902.424498 302.780263 8.760751e-12
freq = eig_df['Freq.']['Mode 1']
period = 1/freq
print(f'Oscillation period from small signal analysis: T = {period:0.2f} s')
Oscillation period from small signal analysis: T = 4.58 s
p.simulate([{'t_end':1, 'theta':np.deg2rad(-5)},
            {'t_end':50,'f_x':0}],'prev');
time = p.T[:,0]
theta = np.rad2deg(p.get_values('theta'))

idx_1 = np.where(theta==np.max(theta[(time>7)&(time<11)]))[0][0]
idx_2 = np.where(theta==np.max(theta[(time>10)&(time<14)]))[0][0]
t_1 = time[idx_1]
t_2 = time[idx_2]

period_sim = t_2 - t_1

print(f'Oscillation period from simulation: T = {period_sim:0.2f} s')

plt.close('all')
fig, axes = plt.subplots(nrows=1,ncols=1, figsize=(5, 3), dpi=100)

axes.plot(p.T, np.rad2deg(p.get_values('theta')), label=f'$\theta$')
axes.grid()
axes.set_ylabel('$\\theta (º)$')
Oscillation period from simulation: T = 1.01 s
Text(0, 0.5, '$\\theta (º)$')
(85**(1/3))*5
21.984148360790897

Animation

M_list = [10,10,85]
theta_ini_list = [5,10,10]

for M,theta_ini in zip(M_list,theta_ini_list):
    
    p.simulate([{'t_end':1, 'theta':np.deg2rad(-theta_ini),'M':M},
                {'t_end':50,'f_x':0}],'prev');

    fig, ax = plt.subplots() 
    line, = ax.plot([], [], 'b', lw=2) 
    pivot, = ax.plot(0, 0, 'bo', ms=7) 
    
    bob, = ax.plot([], [], 'ro', ms=(M**(1/3))*5)  

    txt = ax.text(1,0.5,f't = 0 s')
    txt_theta = ax.text(1,0.0,f'$\\theta = 0 º')
    def init():  
        ax.set_xlim(-1.5,1.5)  
        ax.set_ylim(-1.2*L,1) 


    def update(t): 
        pos_x = np.interp(t,p.T[:,0],p.get_values('pos_x'))  
        pos_y = np.interp(t,p.T[:,0],p.get_values('pos_y')) 
        theta = np.interp(t,p.T[:,0],p.get_values('theta')) 
        bob.set_data(pos_x, pos_y)
        txt.set_text(f't = {t:5.1f} s')
        txt_theta.set_text(f'$\\theta$ = {np.rad2deg(theta):5.1f} º')
        x = [0,pos_x]  
        y = [0,pos_y] 
        line.set_data(x, y)    

    Dt_ani = 1/25    
    ani = FuncAnimation(fig, update,frames=np.arange(0,50,Dt_ani),init_func=init,interval=Dt_ani, blit=True);
    writer = PillowWriter(fps=np.ceil(1/Dt_ani))  
    ani.save(f"pendulum_{M:0.0f}kg_{theta_ini:0.0f}deg.png", writer=writer)  
from IPython.display import HTML
ani = FuncAnimation(fig, update,frames=np.arange(0,50,Dt_ani),init_func=init,interval=Dt_ani);
    writer = PillowWriter(fps=np.ceil(1/Dt_ani))
HTML(ani.to_html5_video())
import numpy as np
import matplotlib.pyplot as plt


r = np.arange(0, 2, 0.01)
theta = 2 * np.pi * r

ax = plt.subplot(projection='polar')
ax.plot(theta, r)
ax.set_rmax(2)
ax.set_rticks([0.5, 1, 1.5, 2])  # Less radial ticks
ax.set_rlabel_position(-22.5)  # Move radial labels away from plotted line
ax.grid(True)

ax.set_title("A line plot on a polar axis", va='bottom')
plt.show()
<ipython-input-131-bce1d8383462>:8: MatplotlibDeprecationWarning: Adding an axes using the same arguments as a previous axes currently reuses the earlier instance.  In a future version, a new instance will always be created and returned.  Meanwhile, this warning can be suppressed, and the future behavior ensured, by passing a unique label to each axes instance.
  ax = plt.subplot(projection='polar')
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = plt.plot([], [], 'ro')

def init():
    ax.set_xlim(0, 2*np.pi)
    ax.set_ylim(-1, 1)
    return ln,

def update(frame):
    xdata.append(frame)
    ydata.append(np.sin(frame))
    ln.set_data(xdata, ydata)
    return ln,

ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 128),
                    init_func=init, blit=True)
plt.show()

import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np

t = np.linspace(0,2*np.pi)
x = np.sin(t)

fig, ax = plt.subplots()
ax.axis([0,2*np.pi,-1,1])
l, = ax.plot([],[])

def animate(i):
    l.set_data(t[:i], x[:i])

ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))

from IPython.display import HTML
HTML(ani.to_html5())
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-178-d48a5f189687> in <module>
     16 
     17 from IPython.display import HTML
---> 18 HTML(ani.to_html5())

AttributeError: 'FuncAnimation' object has no attribute 'to_html5'